package org.spp.voronoi;

import org.spp.utilities.Point;
import org.spp.utilities.SetUtils;

import java.util.List;
import java.util.ArrayList;

/**
 * Edge3D.java
 * @author Ilio Catallo, Eleonora Ciceri
 * @version 1.0
 * @see Edge
 * 
 * Description: class that specializes the edge of the Voronoi Diagram in case
 *              of tridimensional points
 * 
 * Date: Jul 10, 2011
 */
public class Edge3D extends Edge{
   
    /**
     * Constructor for the clas Edge3D
     * @param startVertex
     * @param endVertex
     * @param facets 
     */
    public Edge3D(Vertex3D startVertex, Vertex3D endVertex, List<Facet> facets){    
        super(startVertex, endVertex, facets);
    }
    
    /**
     * Constructor for the class Edge3D
     * @param startVertex
     * @param endVertex
     * @param centroid
     * @param facets 
     */
    public Edge3D(Vertex startVertex, Vertex endVertex, Centroid centroid, List<Facet> facets) {    
        super(startVertex, endVertex, centroid, facets);
    }
      
    /**
     * Method that computes the direction vector of the edge
     * @return direction 
     */
    @Override
    protected double[] computeDirection() {
        // Variables
        double[] plane1Coefficients = ((Plane)facets.get(0)).getCoefficients();
        double[] plane2Coefficients = ((Plane)facets.get(1)).getCoefficients();
        
        // Build the normal vectors to the planes
        double[] plane1Normal = new double[]{plane1Coefficients[0], plane1Coefficients[1], plane1Coefficients[2]};
        double[] plane2Normal = new double[]{plane2Coefficients[0], plane2Coefficients[1], plane2Coefficients[2]};
        
        // Compute the direction & normalize
        double[] newDirection = Point.crossProduct(plane1Normal, plane2Normal);
        newDirection = Point.normalize(newDirection);
        
        // Possibly correct the direction sign
        newDirection = correctDirection(newDirection);
        
        return newDirection;
    }
        
    /**
     * Given the two facets that create the edge, the method finds which cells
     * have in common the edge
     * @return adjCells 
     */
    @Override
    protected List<Cell> findAdjCells(){
        // Variables
        List<Cell> adjCells = new ArrayList<Cell>();
        
        // The edge comes from a corner, so it doesn't divide any cell
        if (facets.get(0).isInBoundedRegion() && facets.get(1).isInBoundedRegion())
            return null;
        
        // One of the facets come from the bounding box
        if (facets.get(0).isInBoundedRegion() || facets.get(1).isInBoundedRegion())
            adjCells = SetUtils.findIntersection(facets.get(0).getCells(), facets.get(1).getCells());
            
        else
            adjCells = SetUtils.findUnion(facets.get(0).getCells(), facets.get(1).getCells());
        
        // We are interested only in the adjacent cells so we remove the cell associated
        // to the centroid of the edge
        adjCells.remove(centroid.getCell());
        
        return adjCells;
    }
    
}
